#include "dxyReflectClass.h"

namespace dxy::reflect
{

DxyRelfectObject::~DxyRelfectObject() {}

DxyReflectClass & DxyReflectClass::getInstance()
{
    static DxyReflectClass instance;
    return instance;
}

DxyReflectClass::DxyReflectClass()
{

}

DxyReflectClass::~DxyReflectClass()
{
    
}

std::shared_ptr<DxyRelfectObject> DxyReflectClass::getClassByName(const std::string & className)
{
    auto it = m_classMap.find(className);
    if(it == m_classMap.end())
    {
        return nullptr;
    }
    return std::shared_ptr<DxyRelfectObject>(it->second());
}

void DxyReflectClass::registerClassFieldByName(const std::string & className, const std::string & fieldName, size_t offset)
{
    auto it = m_classMap.find(className);
    if(it == m_classMap.end()) throw std::exception();
    if(m_classFieldMap.find(className) == m_classFieldMap.end())
    {
        m_classFieldMap[className] = std::map<std::string, size_t>();
    }
    m_classFieldMap[className][fieldName] = offset;
}

void DxyReflectClass::registerClassFunctionByName(const std::string & className, const std::string & funcName, size_t ptr)
{
    auto it = m_classMap.find(className);
    if(it == m_classMap.end()) throw std::exception();
    if(m_classFunctionMap.find(className) == m_classFieldMap.end())
    {
        m_classFunctionMap[className] = std::map<std::string, size_t>();
    }
    m_classFunctionMap[className][funcName] = ptr;
}

bool DxyReflectClass::isExistClass(const std::string & className)
{
    auto it = m_classMap.find(className);
    if(it == m_classMap.end())
    {
        return false;
    }
    return true;
}

bool DxyReflectClass::isExistFunction(const std::string & className, const std::string & funcName)
{
    auto it = m_classMap.find(className);
    if(it == m_classMap.end()) return false; 
    if(m_classFunctionMap[className].find(funcName) == m_classFieldMap[className].end())
    {
        return false;
    }
    return true;
}

bool DxyReflectClass::isExistField(const std::string & className, const std::string & fieldName)
{
    auto it = m_classMap.find(className);
    if(it == m_classMap.end()) return false;
    if(m_classFunctionMap[className].find(fieldName) == m_classFunctionMap[className].end())
    {
        return false;
    }
    return true;
}




void DxyRelfectObject::call(const std::string & className, const std::string & funcName)
{
    auto it1 = DxyReflectClass::getInstance().m_classFunctionMap.find(className);
    if(it1 == DxyReflectClass::getInstance().m_classFunctionMap.end()) throw std::exception();
    auto it2 = DxyReflectClass::getInstance().m_classFunctionMap[className].find(funcName);
    if(it2 == DxyReflectClass::getInstance().m_classFunctionMap[className].end()) throw std::exception(); 
    std::function<void (decltype(this))> func = *(std::function<void (decltype(this))>*)(it2->second);
    func(this);
}




}
